package com.jetpackframework.rxmvvm;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.gwm.annotation.mvvm.MvvmSource;
import com.jetpackframework.rxjetpack.Dispose;
import com.jetpackframework.rxjetpack.Observable;
import com.jetpackframework.rxjetpack.Observer;
import com.jetpackframework.rxjetpack.thread.Schedule;
import com.jetpackframework.rxjetpack.thread.Schedules;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

public class BaseViewModel<T> extends ViewModel<T>{
    @Override
    protected void onCreate(LifecycleOwner owner) {
        super.onCreate(owner);
    }

    /**
     * 发送消息调用与之绑定的activity跟fragment
     * @param data   数据
     * @param name  数据名称
     */
    protected void postValue(T data,String name){
        toObservable(Observable.just(data),name);
    }
    /**
     * 发送消息调用与之绑定的activity跟fragment
     * @param observable 用Observable封装的数据
     * @param name  数据名称
     */
    protected void toObservable(Observable<T> observable,String name){
        toObservable(observable.name(name));
    }
    private void toObservable(Observable<ObservableName.ObservableEntity<T>> observable){
        toObservable(observable, Schedules.io(),Schedules.androidMainThread());
    }
    private void toObservable(Observable<ObservableName.ObservableEntity<T>> observable, Schedule observableScedule,Schedule subscribeSchedule){
        observable.observeOn(observableScedule).subscribeOn(subscribeSchedule).subscribe(new LifecycleObserver<T>(owner));
    }

    /**
     * 执行任务  子线程任务
     * @param runnable
     */
    public void runnableInThread(Runnable runnable){
        Schedule.Worker worker = Schedules.io().createWorker();
        worker.schedule(runnable);
    }
    /**
     * 执行任务  子线程延时任务
     * @param runnable
     */
    public void runnableInThreadByTimer(Runnable runnable, long delay, TimeUnit unit){
        Schedule.Worker worker = Schedules.io().createWorker();
        worker.scheduleTimer(runnable,delay,unit);
    }
    private static final class LifecycleObserver<T> implements Observer<ObservableName.ObservableEntity<T>> {

        private final LifecycleOwner owner;

        public LifecycleObserver(LifecycleOwner owner) {
            this.owner = owner;
        }

        @Override
        public void onSubscribe(Dispose dispose) {

        }

        @Override
        public void onNext(ObservableName.ObservableEntity<T> observableEntity) throws Exception {
            if (owner.getLifecycle().getCurrentState() == Lifecycle.State.CREATED || owner.getLifecycle().getCurrentState() == Lifecycle.State.STARTED || owner.getLifecycle().getCurrentState() == Lifecycle.State.RESUMED) {
                final Method[] methods = owner.getClass().getDeclaredMethods();
                for (int i = 0; i < methods.length; i++) {
                    if (methods[i].isAnnotationPresent(MvvmSource.class)) {
                        MvvmSource mvvmSource = methods[i].getAnnotation(MvvmSource.class);
                        if (observableEntity.getName().equals(mvvmSource.value())) {
                            observableEntity.getObservable().subscribe(new MethodObserver<T>(methods[i], owner));
                            break;
                        }
                    }
                }
            }
        }

        @Override
        public void onError(Throwable t) {

        }

        @Override
        public void onComplete() {

        }
    }
    private static final class MethodObserver<T> implements Observer<T>{
        private final Method method;
        private final LifecycleOwner owner;

        public MethodObserver(Method method, LifecycleOwner owner) {
            this.method = method;
            this.owner = owner;
        }

        @Override
        public void onSubscribe(Dispose dispose) {

        }

        @Override
        public void onNext(T t) throws Exception {
            method.invoke(owner,t);
        }

        @Override
        public void onError(Throwable t) {

        }

        @Override
        public void onComplete() {

        }
    }
}
